package com.aocore.packet;

import com.aocore.packet.GS.*;
import com.aocore.proxy.compression.Huffman;
import java.nio.ByteBuffer;

/**
 *
 * @author derek
 */
public abstract class GSPacket extends Packet
{
    public GSPacket(byte... data)
    {
        super(data);
    }

    public static GSPacket create(byte... data)
    {
        try
        {
            switch (data[0] & 0xFF)
            {
                case 0x00: return new GameLoading(data);
                case 0x01: return new GameLogonReceipt(data);
                case 0x02: return new GameLogonSuccess(data);
                case 0x03: return new LoadAct(data);
                case 0x04: return new LoadDone(data);
                case 0x05: return new UnloadDone(data);
                case 0x06: return new GameLogoutSuccess(data);
                case 0x07: return new MapAdd(data);
                case 0x08: return new MapRemove(data);
                case 0x09: return new AssignWarp(data);
                case 0x0A: return new RemoveGroundUnit(data);
                case 0x0B: return new GameHandshake(data);
                case 0x0C: return new NPCGetHit(data);
                case 0x0D: return new PlayerStop(data);
                case 0x0E: return new SetGameObjectMode(data);
                case 0x0F: return new PlayerMove(data);
                case 0x10: return new PlayerMoveToTarget(data);
                case 0x11: return new ReportKill(data);
                case 0x15: return new PlayerReassign(data);
                case 0x18: return new PlayerLifeManaChange1(data);
                case 0x19: return new SmallGoldAdd(data);
                case 0x1A: return new ByteToExperience(data);
                case 0x1B: return new WordToExperience(data);
                case 0x1C: return new DWordToExperience(data);
                case 0x1D: return new AttributeByte(data);
                case 0x1E: return new AttributeWord(data);
                case 0x1F: return new AttributeDWord(data);
                case 0x20: return new PlayerAttributeNotification(data);
                case 0x21: return new UpdateSkill(data);
                case 0x22: return new UpdateItemSkill(data);
                case 0x23: return new AssignSkill(data);
                case 0x26: return new GameMessage(data);
                case 0x27: return new NPCInfo(data);
                case 0x28: return new UpdateQuestInfo(data);
                case 0x29: return new UpdateGameQuestLog(data);
                case 0x2A: return new TransactionComplete(data);
                case 0x2C: return new PlaySound(data);
                case 0x3E: return new UpdateItemStats(data);
                case 0x3F: return new UseStackableItem(data);
                case 0x42: return new PlayerClearCursor(data);
                case 0x47: return new Relator1(data);
                case 0x48: return new Relator2(data);
                case 0x4C: return new UnitUseSkillOnTarget(data);
                case 0x4D: return new UnitUseSkill(data);
                case 0x4E: return new MercForHire(data);
                case 0x4F: return new MercForHireListStart(data);
                case 0x51: return new AssignGameObject(data);
                case 0x52: return new UpdateQuestLog(data);
                case 0x53: return new PartyRefresh(data);
                case 0x59: return new AssignPlayer(data);
                case 0x5A: return new InformationMessage(data);
                case 0x5B: return new PlayerInGame(data);
                case 0x5C: return new PlayerLeaveGame(data);
                case 0x5D: return new QuestItemState(data);
                case 0x60: return new PortalInfo(data);
                case 0x63: return new OpenWaypoint(data);
                case 0x65: return new PlayerKillCount(data);
                case 0x67: return new NPCMove(data);
                case 0x68: return new NPCMoveToTarget(data);
                case 0x69: return new SetNPCMode(data);
                case 0x6B: return new NPCAction(data);
                case 0x6C: return new MonsterAttack(data);
                case 0x6D: return new NPCStop(data);
                case 0x74: return new PlayerCorpseVisible(data);
                case 0x75: return new AboutPlayer(data);
                case 0x76: return new PlayerInSight(data);
                case 0x77: return new UpdateItemUI(data);
                case 0x78: return new AcceptTrade(data);
                case 0x79: return new GoldTrade(data);
                case 0x7A: return new SummonAction(data);
                case 0x7B: return new AssignSkillHotkey(data);
                case 0x7C: return new UseSpecialItem(data);
                case 0x7D: return new SetItemState(data);
                case 0x7F: return new PartyMemberUpdate(data);
                case 0x81: return new AssignMerc(data);
                case 0x82: return new PortalOwnership(data);
                case 0x8A: return new NPCWantsInteract(data);
                case 0x8B: return new PlayerPartyRelationship(data);
                case 0x8C: return new PlayerRelationship(data);
                case 0x8D: return new AssignPlayerToParty(data);
                case 0x8E: return new AssignPlayerCorpse(data);
                case 0x8F: return new Pong(data);
                case 0x90: return new PartyMemberPulse(data);
                case 0x94: return new SkillsLog(data);
                case 0x95: return new PlayerLifeManaChange(data);
                case 0x96: return new WalkVerify(data);
                case 0x97: return new SwitchWeaponSet(data);
                case 0x99: return new ItemTriggerSkill(data);
                case 0x9C: return new WorldItemAction(data);
                case 0x9D: return new OwnedItemAction(data);
                case 0x9E: return new MercAttributeByte(data);
                case 0x9F: return new MercAttributeWord(data);
                case 0xA0: return new MercAttributeDWord(data);
                case 0xA1: return new MercByteToExperience(data);
                case 0xA2: return new MercWordToExperience(data);
                case 0xA7: return new DelayedState(data);
                case 0xA8: return new SetState(data);
                case 0xA9: return new EndState(data);
                case 0xAA: return new AddUnit(data);
                case 0xAB: return new NPCHeal(data);
                case 0xAC: return new AssignNPC(data);
                case 0xAE: return new WardenCheck(data);
                case 0xAF: return new RequestLogonInfo(data);
                case 0xB0: return new GameOver(data);
                default: throw new IllegalArgumentException("invalid GS packet id " + data[0]);
            }
        }
        catch (Exception e)
        {
            e.printStackTrace(System.err);
            GSPacket packet = new Invalid(data);
            System.err.println("CS: " + packet.getBytes());
            return packet;
        }
    }

    @Override
    public void write(ByteBuffer byteBuffer)
    {
        byte[] compressed_data = new byte[2048];
        int compressed_length = Huffman.compressDataContent(data, compressed_data);

        byte[] header_data = new byte[2];
        int header_length = Huffman.createDataHeader(compressed_length, header_data, 2);

        byteBuffer.put(header_data, 0, header_length);
        byteBuffer.put(compressed_data, 0, compressed_length);
    }
}
